]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
Add an OSD monitor labeler exposed on DBus
authorRui Matos <tiagomatos@gmail.com>
Mon, 26 Jan 2015 14:52:10 +0000 (15:52 +0100)
committerRui Matos <tiagomatos@gmail.com>
Thu, 5 Feb 2015 12:34:52 +0000 (13:34 +0100)
This DBus API is intended to be used by gnome-control-center's
displays panel to show monitor labels.

Each output (i.e. hardware monitor) identified by its
org.gnome.Mutter.DisplayConfig API ID has at most one label. On
mirrored setups, all the labels for outputs corresponding to the same
logical monitor (i.e. showing the same contents in the same mode) are
shown together.

At most, only one DBus client at a time is allowed to show labels.

https://bugzilla.gnome.org/show_bug.cgi?id=743744

data/theme/gnome-shell.css
js/js-resources.gresource.xml
js/ui/main.js
js/ui/osdMonitorLabeler.js [new file with mode: 0644]
js/ui/shellDBus.js

index 7beede392c30e19ef555278eee7e76b7d9dc9020..dc9a006b174fd34942a2bdad02c1f1c37e38ec13 100644 (file)
@@ -1812,6 +1812,9 @@ StScrollBar StButton#vhandle:active {
     text-align: center;
     font-weight: bold;
     spacing: 1em;
+    margin: 32px;
+    min-width: 64px;
+    min-height: 64px;
 }
 
 .osd-window .level {
@@ -1820,6 +1823,10 @@ StScrollBar StButton#vhandle:active {
     background-color: rgba(190,190,190,0.2);
 }
 
+.osd-monitor-label {
+    font-size: 3em;
+}
+
 /* App Switcher */
 .switcher-popup {
     padding: 8px;
index 02d2dd001f1103b738c454cbc9d4adfed1fadca2..439c0aad92c438330d8a207e31fa1fad61d96b17 100644 (file)
@@ -64,6 +64,7 @@
     <file>ui/modalDialog.js</file>
     <file>ui/notificationDaemon.js</file>
     <file>ui/osdWindow.js</file>
+    <file>ui/osdMonitorLabeler.js</file>
     <file>ui/overview.js</file>
     <file>ui/overviewControls.js</file>
     <file>ui/panel.js</file>
index 32c864475532c297609c3b165374dceae46b86ac..aecf5fbcaa0de26b78d0ef6c10d65fc5b0369a3e 100644 (file)
@@ -21,6 +21,7 @@ const Keyboard = imports.ui.keyboard;
 const MessageTray = imports.ui.messageTray;
 const ModalDialog = imports.ui.modalDialog;
 const OsdWindow = imports.ui.osdWindow;
+const OsdMonitorLabeler = imports.ui.osdMonitorLabeler;
 const Overview = imports.ui.overview;
 const Panel = imports.ui.panel;
 const Params = imports.misc.params;
@@ -57,6 +58,7 @@ let notificationDaemon = null;
 let windowAttentionHandler = null;
 let ctrlAltTabManager = null;
 let osdWindowManager = null;
+let osdMonitorLabeler = null;
 let sessionMode = null;
 let shellDBusService = null;
 let shellMountOpDBusService = null;
@@ -150,6 +152,7 @@ function _initializeUI() {
     xdndHandler = new XdndHandler.XdndHandler();
     ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
     osdWindowManager = new OsdWindow.OsdWindowManager();
+    osdMonitorLabeler = new OsdMonitorLabeler.OsdMonitorLabeler();
     overview = new Overview.Overview();
     wm = new WindowManager.WindowManager();
     magnifier = new Magnifier.Magnifier();
diff --git a/js/ui/osdMonitorLabeler.js b/js/ui/osdMonitorLabeler.js
new file mode 100644 (file)
index 0000000..9d519f5
--- /dev/null
@@ -0,0 +1,141 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Clutter = imports.gi.Clutter;
+const Gio = imports.gi.Gio;
+const St = imports.gi.St;
+
+const Lang = imports.lang;
+const Main = imports.ui.main;
+const Tweener = imports.ui.tweener;
+const Meta = imports.gi.Meta;
+
+const FADE_TIME = 0.1;
+
+const OsdMonitorLabel = new Lang.Class({
+    Name: 'OsdMonitorLabel',
+
+    _init: function(monitor, label) {
+        this._actor = new St.Widget({ opacity: 0,
+                                      x_expand: true,
+                                      y_expand: true });
+
+        this._monitor = monitor;
+
+        this._box = new St.BoxLayout({ style_class: 'osd-window',
+                                       vertical: true });
+        this._actor.add_actor(this._box);
+
+        this._label = new St.Label({ style_class: 'osd-monitor-label',
+                                     text: label });
+        this._box.add(this._label);
+
+        Main.uiGroup.add_child(this._actor);
+        Main.uiGroup.set_child_above_sibling(this._actor, null);
+        this._position();
+
+        Meta.disable_unredirect_for_screen(global.screen);
+        Tweener.addTween(this._actor,
+                         { opacity: 255,
+                           time: FADE_TIME,
+                           transition: 'easeOutQuad' });
+    },
+
+    _position: function() {
+        let workArea = Main.layoutManager.getWorkAreaForMonitor(this._monitor);
+
+        if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
+            this._box.x = workArea.x + (workArea.width - this._box.width);
+        else
+            this._box.x = workArea.x;
+
+        this._box.y = workArea.y;
+    },
+
+    destroy: function() {
+        Tweener.addTween(this._actor,
+                         { opacity: 0,
+                           time: FADE_TIME,
+                           transition: 'easeOutQuad',
+                           onComplete: Lang.bind(this, function() {
+                               this._actor.destroy();
+                               Meta.enable_unredirect_for_screen(global.screen);
+                           })
+                         });
+    }
+});
+
+const OsdMonitorLabeler = new Lang.Class({
+    Name: 'OsdMonitorLabeler',
+
+    _init: function() {
+        this._monitorManager = Meta.MonitorManager.get();
+        this._client = null;
+        this._clientWatchId = 0;
+        this._osdLabels = [];
+        this._monitorLabels = null;
+        Main.layoutManager.connect('monitors-changed',
+                                    Lang.bind(this, this._reset));
+        this._reset();
+    },
+
+    _reset: function() {
+        for (let i in this._osdLabels)
+            this._osdLabels[i].destroy();
+        this._osdLabels = [];
+        this._monitorLabels = new Map();
+        let monitors = Main.layoutManager.monitors;
+        for (let i in monitors)
+            this._monitorLabels.set(monitors[i].index, []);
+    },
+
+    _trackClient: function(client) {
+        if (this._client)
+            return (this._client == client);
+
+        this._client = client;
+        this._clientWatchId = Gio.bus_watch_name(Gio.BusType.SESSION, client, 0, null,
+                                                 Lang.bind(this, function(c, name) {
+                                                     this.hide(name);
+                                                 }));
+        return true;
+    },
+
+    _untrackClient: function(client) {
+        if (!this._client || this._client != client)
+            return false;
+
+        Gio.bus_unwatch_name(this._clientWatchId);
+        this._clientWatchId = 0;
+        this._client = null;
+        return true;
+    },
+
+    show: function(client, params) {
+        if (!this._trackClient(client))
+            return;
+
+        this._reset();
+
+        for (let id in params) {
+            let monitor = this._monitorManager.get_monitor_for_output(id);
+            if (monitor == -1)
+                continue;
+            this._monitorLabels.get(monitor).push(params[id].deep_unpack());
+        }
+
+        // In mirrored display setups, more than one physical outputs
+        // might be showing the same logical monitor. In that case, we
+        // join each output's labels on the same OSD widget.
+        for (let [monitor, labels] of this._monitorLabels.entries()) {
+            labels.sort();
+            this._osdLabels.push(new OsdMonitorLabel(monitor, labels.join(' ')));
+        }
+    },
+
+    hide: function(client) {
+        if (!this._untrackClient(client))
+            return;
+
+        this._reset();
+    }
+});
index 7e45d84adf9789b9f19a61ae6a31fd8decea185b..14dba7292a92e885e9a425e14dd0367a35a6f83b 100644 (file)
@@ -25,6 +25,10 @@ const GnomeShellIface = '<node> \
 <method name="ShowOSD"> \
     <arg type="a{sv}" direction="in" name="params"/> \
 </method> \
+<method name="ShowMonitorLabels"> \
+    <arg type="a{uv}" direction="in" name="params" /> \
+</method> \
+<method name="HideMonitorLabels" /> \
 <method name="FocusApp"> \
     <arg type="s" direction="in" name="id"/> \
 </method> \
@@ -240,6 +244,17 @@ const GnomeShell = new Lang.Class({
         this._grabbers.delete(name);
     },
 
+    ShowMonitorLabelsAsync: function(params, invocation) {
+        let sender = invocation.get_sender();
+        let [dict] = params;
+        Main.osdMonitorLabeler.show(sender, dict);
+    },
+
+    HideMonitorLabelsAsync: function(params, invocation) {
+        let sender = invocation.get_sender();
+        Main.osdMonitorLabeler.hide(sender);
+    },
+
 
     Mode: global.session_mode,